package com.aloha.springframework.aop.aspectj;

import org.aopalliance.aop.Advice;
import org.aspectj.lang.ProceedingJoinPoint;

import java.lang.reflect.Method;

/**
 * @author DaiZhiHeng
 * @description 通知的抽象类
 * @date 2023/8/2 22:29
 */
public abstract class AbstractAspectJAdvice implements Advice {

    // 获取添加@Aspect注解的类工厂
    private final AspectInstanceFactory aspectInstanceFactory;

    // 添加@Aspect注解的类中的增强方法
    private final Method aspectJAdviceMethod;

    public AbstractAspectJAdvice(Method aspectJAdviceMethod, AspectInstanceFactory aspectInstanceFactory) {
        aspectJAdviceMethod.setAccessible(true);
        this.aspectJAdviceMethod = aspectJAdviceMethod;
        this.aspectInstanceFactory = aspectInstanceFactory;
    }

    protected Object invokeAdviceMethod(ProceedingJoinPoint pjp) throws Throwable {
        int paramCount = aspectJAdviceMethod.getParameterCount();
        Object[] args = new Object[paramCount];
        if (pjp != null) { // @Around通知必须要参数
            if (paramCount == 0) throw new RuntimeException("环绕通知的参数中缺少 ProceedingJoinPoint");
            args[0] = pjp;
        }
        return invokeAdviceMethod(args);
    }

    // 调用通知方法
    private Object invokeAdviceMethod(Object[] args) throws Throwable {
        return aspectJAdviceMethod.invoke(aspectInstanceFactory.getAspectInstance(), args);
    }
}
